package com.egao.common.module.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.elasticsearch.entity.ElasticSearchConstants;
import com.egao.common.component.elasticsearch.service.ElasticSearchService;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.exception.ParameterException;
import com.egao.common.core.utils.ExcelUtils;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.module.company.constants.*;
import com.egao.common.module.company.entity.*;
import com.egao.common.module.company.entity.vo.*;
import com.egao.common.module.company.mapper.PreachCloudMapper;
import com.egao.common.module.company.service.*;
import com.egao.common.module.company.utils.CompanyUtil;
import com.egao.common.module.push.constants.PushConstants;
import com.egao.common.module.push.entity.PositionMatching;
import com.egao.common.module.push.entity.PushMsg;
import com.egao.common.module.push.service.PositionMatchingService;
import com.egao.common.module.push.service.PushMsgService;
import com.egao.common.module.pushInformation.service.PushInformationService;
import com.egao.common.module.system.constants.EmailConstants;
import com.egao.common.module.system.entity.User;
import com.egao.common.module.system.service.EmailService;
import com.egao.common.module.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.ExecutorService;

/**
 * 空中宣讲会(PreachCloud)表服务实现类
 *
 * @author dl
 * @since 2021-03-01 10:28:55
 */
@Service("preachCloudService")
@Slf4j
public class PreachCloudServiceImpl extends ServiceImpl<PreachCloudMapper, PreachCloud> implements PreachCloudService {

    @Autowired
    private EmailService emailService;
    @Autowired
    private PositionService positionService;
    @Autowired
    private AttachmentService attachmentService;
    @Autowired
    private CompanyCheckRecordService companyCheckRecordService;
    @Autowired
    private ElasticSearchService elasticSearchService;
    @Resource(name = "taskRunnerExecutor")
    private ExecutorService asyncExecutorService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private UserService userService;
    @Resource
    private PushInformationService pushInformationService;

    private final Logger logger = LoggerFactory.getLogger(PreachCloudServiceImpl.class.getName());

    @Override
    public List<PreachCloudListVO> listPage(PageParam<PreachCloudListVO> page) {
        // 申请时间
        page = (PageParam<PreachCloudListVO>) CompanyUtil.putApplyTime(page);
        Map<String, Object> map = page.getPageData();
        // 单位查询
        if (map.get(CompanyConstants.USER) != null) {
            Integer userId = (Integer) map.get(CompanyConstants.USER);
            Company company = positionService.getCompanyByUserId(userId);
            if (company == null) {
                throw new BusinessException("单位不存在");
            }
            page.put("companyId", company.getId());
        }
        return baseMapper.listPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult savePreachCloud(PreachCloudFormVO preachCloudFormVO) {
        verifyPreachCloud(preachCloudFormVO);

        Company company = positionService.getCompanyByUserId(preachCloudFormVO.getCreateBy());
        if (company == null) {
            throw new BusinessException("单位不存在");
        }

        preachCloudFormVO.setCompanyId(company.getId());
        preachCloudFormVO.setCompanyName(company.getName());

        // 复制宣讲会vo到实体
        PreachCloud preachCloud = new PreachCloud();
        BeanUtil.copyProperties(preachCloudFormVO, preachCloud);

        preachCloud.setInvalid(PreachCloudConstants.VALID);

        if (!save(preachCloud)) {
            return JsonResult.error("保存失败");
        }

        // 保存附件
        attachmentService.saveAttach(preachCloudFormVO.getAttachments(), preachCloud.getId(), AttachmentConstants.TYPE_PREACH_CLOUD);

        // 保存推荐信息
        pushInformationService.save(preachCloud.getCompanyId(), 3, preachCloud.getId(), preachCloud.getTitle());

        return JsonResult.ok("保存成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult checkPreachCloud(PreachCloudFormVO preachCloudFormVO) {
        PreachCloud preachCloud = getPreachCloudByFormVO(preachCloudFormVO);
        String oldState = preachCloud.getState();
        BeanUtil.copyProperties(preachCloudFormVO, preachCloud);
        if (updateById(preachCloud)) {
            attachmentService.deleteAttach(preachCloud.getId(), AttachmentConstants.TYPE_PREACH_CLOUD);
            attachmentService.saveAttach(preachCloudFormVO.getAttachments(), preachCloud.getId(), AttachmentConstants.TYPE_PREACH_CLOUD);

            CompanyCheckRecord companyCheckRecord = new CompanyCheckRecord();
            companyCheckRecord.setCompanyId(preachCloud.getCompanyId());
            companyCheckRecord.setState(preachCloud.getState());
            companyCheckRecord.setStateContent(preachCloud.getStateContent());
            companyCheckRecord.setCheckUserId(preachCloudFormVO.getCheckUserId());
            companyCheckRecord.setType(CheckRecordConstants.CHECK_PREACH_CLOUD);
            companyCheckRecord.setBusinessId(preachCloud.getId());
            companyCheckRecordService.save(companyCheckRecord);

            asyncExecutorService.submit(() -> {
                log.info("开始空中宣讲会推送消息");
                long beginTime = System.currentTimeMillis();
                //需要发送邮件通知
                if(CompanyConstants.SUCCESS.equals(preachCloud.getEmailFlag())) {
                    //发送邮件
                    Company company = companyService.getById(preachCloud.getCompanyId());
                    if (company != null) {
                        User user = userService.getById(company.getUserId());
                        if (user != null) {
                            String[] email = {user.getUsername()};
                            emailService.sendTextEmail(EmailConstants.TITLE_PREACH_CLOUD_CHECK, preachCloud.getStateContent(), email);
                        }
                    }
                }

                // if (PushConstants.YES.equals(preachCloud.getPushFlag()) && CheckRecordConstants.CHECK_SUCCESS.equals(preachCloudFormVO.getState()) && CheckRecordConstants.CHECKING.equals(oldState)) {
                //     pushMsgService.push(preachCloud.getId(), preachCloud.getTitle(), CheckRecordConstants.CHECK_PREACH_CLOUD, preachCloud.getHoldTime());
                // }

                // 审核通过 更新推送信息
                if (CheckRecordConstants.CHECK_SUCCESS.equals(preachCloud.getState())) {
                    pushInformationService.checkPushState(3, preachCloud.getId());
                }

                // 保存es
                if (CheckRecordConstants.CHECK_SUCCESS.equals(preachCloud.getState())) {
                    String id = ElasticSearchConstants.INFORMATION_PREACH_CLOUD + "-" + preachCloud.getId();
                    elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
                    preachCloud.setHoldAddress(preachCloud.getHoldUrl());
                    elasticSearchService.save(preachCloud);
                }

                long finishTime = System.currentTimeMillis();
                long overTime = (finishTime - beginTime) / 1000;
                log.info("完成招聘信息推荐信息线程任务：{} 秒", overTime);
                log.info("结束空中宣讲会推送消息");
            });


            return JsonResult.ok("提交成功");
        }
        return JsonResult.error("提交失败");
    }

    @Override
    public JsonResult removePreachCloud(PreachCloudFormVO preachCloudFormVO) {
        PreachCloud preachCloud = getPreachCloudByFormVO(preachCloudFormVO);

        if (removeById(preachCloud)) {
            attachmentService.deleteAttach(preachCloud.getId(), AttachmentConstants.TYPE_PREACH_CLOUD);

            String id = ElasticSearchConstants.INFORMATION_PREACH_CLOUD + "-" + preachCloud.getId();
            elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    @Override
    public JsonResult detail(Integer id) {
        if (id == null) {
            throw new ParameterException("空中宣讲会信息编号为空");
        }

        PreachCloud preachCloud = getById(id);
        if (preachCloud == null) {
            throw new BusinessException("空中宣讲会信息不存在");
        }

        PreachCloudFormVO preachCloudFormVO = new PreachCloudFormVO();
        BeanUtil.copyProperties(preachCloud, preachCloudFormVO);

        // 单位发布需要查询职位
        if (preachCloud.getPositionIds() != null) {
            List<Position> positions = positionService.getPositionByIds(preachCloud.getPositionIds());
            if (positions != null && positions.size() > 0) {
                preachCloudFormVO.setPositions(positions);
            }
        }

        // 查询发布的附件
        List<Attachment> attachments = attachmentService.getAttachByBusinessId(id, AttachmentConstants.TYPE_PREACH_CLOUD);
        if (attachments != null && attachments.size() > 0) {
            preachCloudFormVO.setAttachments(attachments);
        }

        return JsonResult.ok("查询成功").setData(preachCloudFormVO);
    }

    @Override
    public JsonResult updatePreachCloud(PreachCloudFormVO preachCloudFormVO) {
        PreachCloud preachCloud = getPreachCloudByFormVO(preachCloudFormVO);
        BeanUtil.copyProperties(preachCloudFormVO, preachCloud);
        //审核状态为待审核
        preachCloud.setState(CompanyConstants.RECRUIT_STATE_DSH);

        if (updateById(preachCloud)) {
            attachmentService.deleteAttach(preachCloud.getId(), AttachmentConstants.TYPE_PREACH_CLOUD);
            attachmentService.saveAttach(preachCloudFormVO.getAttachments(), preachCloud.getId(), AttachmentConstants.TYPE_PREACH_CLOUD);
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @Override
    public JsonResult cancelPreachCloud(PreachCloudFormVO preachCloudFormVO) {
        PreachCloud preachCloud = getPreachCloudByFormVO(preachCloudFormVO);

        //审核状态为待审核
        preachCloud.setInvalid(PreachCloudConstants.cancelType);

        if (updateById(preachCloud)) {
            return JsonResult.ok("取消成功");
        }
        return JsonResult.error("取消失败");
    }

    @Override
    public JsonResult countPreachCloud(PageParam<PreachCloudListVO> page) {
        page = (PageParam<PreachCloudListVO>) CompanyUtil.putApplyTime(page);
        page.getPageData().put("state", CompanyConstants.COMPANY_STATE_PASS);
        page.setSearchCount(false);
        page.setSize(100);
        Map<String, Object> map = new HashMap<>(5);
        Integer total = baseMapper.countTotal(page);
        List<Map<String, Object>> provinceList = baseMapper.countProvince(page);
        List<Map<String, Object>> natureList = baseMapper.countNature(page);
        List<Map<String, Object>> industryList = baseMapper.countIndustry(page);
        List<Map<String, Object>> scaleList = baseMapper.countScale(page);
        map.put("total", total);
        map.put("provinceList", provinceList);
        map.put("natureList", natureList);
        map.put("industryList", industryList);
        map.put("scaleList", scaleList);
        return JsonResult.ok().setData(map);
    }


    /**
     * 获取需要修改宣讲会信息
     * @param preachCloudFormVO 宣讲会表单
     * @return
     */
    private PreachCloud getPreachCloudByFormVO(PreachCloudFormVO preachCloudFormVO) {
        verifyPreachCloud(preachCloudFormVO);

        if (preachCloudFormVO.getId() == null) {
            throw new ParameterException("空中宣讲会编号为空");
        }

        PreachCloud preachCloud = getById(preachCloudFormVO.getId());
        if (preachCloud == null) {
            throw new BusinessException("空中宣讲会信息为空");
        }

        return preachCloud;
    }

    /**
     * 验证空中宣讲会表单是否为空
     * @param preachCloudFormVO 宣讲会表单
     * @return
     */
    private void verifyPreachCloud(PreachCloudFormVO preachCloudFormVO) {
        if (preachCloudFormVO == null) {
            throw new ParameterException("空中宣讲会信息为空");
        }
    }


    @Override
    public void exportExcel(Map<String, Object> page, HttpServletResponse response) {
        Object pageDataObj = page.get("pageData");
        HashMap<String, Object> hashMap = null;
        if (pageDataObj instanceof HashMap) {
            hashMap = (HashMap<String, Object>) pageDataObj;
        } else {
            logger.error("pageData 不是 HashMap 类型");
            return;
        }

        try {
            processHashMap(hashMap);
        } catch (BusinessException e) {
            logger.error("处理查询条件时出错: " + e.getMessage(), e);
            return;
        }
        page.put("pageData", hashMap);

        List<PreachCloudExcelVO> list = baseMapper.listExcel(page);

        String fileName = "preachCloud-" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + ".xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        try (OutputStream out = response.getOutputStream();
             ExcelWriter writer = ExcelUtil.getWriter(true)) {
            // 在第一行之前添加标题、总记录数、企业个数
            List<Object> titleRow = new ArrayList<>();
            if (hashMap.get("createTimeStart") != null && hashMap.get("createTimeEnd") != null) {
                titleRow.add(hashMap.get("createTimeStart").toString().split(" ")[0] + "~" + hashMap.get("createTimeEnd").toString().split(" ")[0] + "空中宣讲会信息");
            } else if (hashMap.get("createTimeStart") != null && hashMap.get("createTimeEnd") == null) {
                titleRow.add(hashMap.get("createTimeStart").toString().split(" ")[0] + "至今" + "空中宣讲会信息");
            } else if (hashMap.get("createTimeStart") == null && hashMap.get("createTimeEnd") != null) {
                titleRow.add("至" + hashMap.get("createTimeEnd").toString().split(" ")[0] + "空中宣讲会信息");
            } else {
                titleRow.add("空中宣讲会信息");
            }
            writer.writeRow(titleRow);

            // 获取总记录数和企业个数
            int totalCount = list.size();
            int companyCount = companyCount(list);
            List<Object> totalRow = new ArrayList<>();
            totalRow.add("空中宣讲会总记录数: " + totalCount);
            totalRow.add("企业个数: " + companyCount);
            writer.writeRow(totalRow);

            excelAddHeaderAlias(writer);
            writer.write(list, true);

            // 设置列自适应宽 必须在 write 以后
            ExcelUtils.autoColumnMaxSizeAll(writer.getSheet());
            writer.flush(out, true);
        } catch (IOException e) {
            logger.error("导出失败 - PreachCloudServiceImpl - exportExcel", e);
        }
    }

    /**
     * 为导出对象设置别名和排序 排序顺序为 add 顺序
     *
     * @param writer ExcelWriter
     */
    public void excelAddHeaderAlias(ExcelWriter writer) {
        writer.addHeaderAlias("title", "标题");
        writer.addHeaderAlias("companyName", "单位名称");
        writer.addHeaderAlias("holdTime", "举办时间");
        writer.addHeaderAlias("holdUrl", "直播地址");
    }

    /**
     * 实现时间段查询包含 timeEnd 当天记录，同时实现多单位、多岗位类型查询
     *
     * @param hashMap
     */
    private void processHashMap(HashMap<String, Object> hashMap) {

        // 发布时间查询
        if (hashMap.get("applyTime") != null) {
            String[] arr = hashMap.get("applyTime").toString().split("~");
            if (arr.length > 0) {
                hashMap.put("createTimeStart", arr[0] + " 00:00:00");
            }
            if (arr.length > 1) {
                hashMap.put("createTimeEnd", arr[1] + " 23:59:59");
            }
        }

        // 单位查询
        if (hashMap.get(CompanyConstants.USER) != null) {
            Integer userId = (Integer) hashMap.get(CompanyConstants.USER);
            Company company = positionService.getCompanyByUserId(userId);
            if (company == null) {
                throw new BusinessException("单位不存在");
            }
            hashMap.put("companyId", company.getId());
        }

        // 查询类型 岗位
        if (hashMap.get(CompanyConstants.JOBS) != null) {
            String jobs = (String) hashMap.get(CompanyConstants.JOBS);
            hashMap.put("jobNameList", jobs.split("，"));
        }
        if (hashMap.get(CompanyConstants.EDUCATION) != null) {
            String education = (String) hashMap.get(CompanyConstants.EDUCATION);
            hashMap.put("educationList", education.split("，"));
        }
        if (hashMap.get(CompanyConstants.JOB_CATEGORY) != null) {
            String jobCategory = (String) hashMap.get(CompanyConstants.JOB_CATEGORY);
            hashMap.put("jobCategoryList", jobCategory.split("，"));
        }
        if (hashMap.get(CompanyConstants.MAJORS) != null) {
            String majors = (String) hashMap.get(CompanyConstants.MAJORS);
            hashMap.put("majorsList", majors.split("，"));
        }
    }

    /**
     * 查询企业个数
     *
     * @param list
     */
    private int companyCount(List<PreachCloudExcelVO> list) {
        Set<String> companyNameSet = new HashSet<>();
        for (PreachCloudExcelVO vo : list) {
            String companyName = vo.getCompanyName();
            if (companyName != null) {
                companyNameSet.add(companyName);
            }
        }
        return companyNameSet.size();
    }
}